package com.gzc.just.play.last.war.centralserver.user.service;

import com.gzc.just.play.last.war.centralserver.user.dto.UserLoginRequest;
import com.gzc.just.play.last.war.centralserver.user.dto.UserRegisterRequest;
import com.gzc.just.play.last.war.centralserver.user.model.User;
import com.gzc.just.play.last.war.centralserver.user.repository.UserRepository;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 用户管理服务
 * 替代C++的CSUserMgr
 */
@Service("central-userService")
@Transactional
public class UserService {
    private static final Logger logger = LoggerFactory.getLogger(UserService.class);
    
    @Autowired
    private UserRepository userRepository;
    
    @Autowired
    private PasswordEncoder passwordEncoder;
    
    // 在线用户缓存
    private final ConcurrentHashMap<Long, User> onlineUsers = new ConcurrentHashMap<>();
    
    // 用户登录会话缓存
    private final ConcurrentHashMap<Long, UserSession> userSessions = new ConcurrentHashMap<>();
    
    /**
     * 用户登录
     */
    public Map<String, Object> login(UserLoginRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            Optional<User> optionalUser = userRepository.findByUsername(request.getUsername());
            if (optionalUser.isEmpty()) {
                result.put("success", false);
                result.put("message", "用户名不存在");
                logger.warn("Login attempt with non-existent username: {}", request.getUsername());
                return result;
            }
            
            User user = optionalUser.get();
            
            // 验证密码
            if (!passwordEncoder.matches(request.getPassword(), user.getPasswordHash())) {
                result.put("success", false);
                result.put("message", "密码错误");
                logger.warn("Login attempt with wrong password for user: {}", user.getUsername());
                return result;
            }
            
            // 更新登录信息
            user.setStatus(User.UserStatus.ONLINE);
            user.setLastLoginTime(LocalDateTime.now());
            user.setIsOnline(true);
            userRepository.save(user);
            
            // 缓存在线用户
            onlineUsers.put(user.getUserId(), user);
            
            // 创建用户会话
            UserSession session = new UserSession();
            session.setUserId(user.getUserId());
            session.setUsername(user.getUsername());
            session.setLoginTime(LocalDateTime.now());
            session.setSessionId(UUID.randomUUID().toString());
            userSessions.put(user.getUserId(), session);
            
            result.put("success", true);
            result.put("message", "登录成功");
            result.put("userId", user.getUserId());
            result.put("sessionId", session.getSessionId());
            result.put("user", user);
            
            logger.info("User login successful: {} (ID: {})", user.getUsername(), user.getUserId());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "登录失败：" + e.getMessage());
            logger.error("Login error", e);
        }
        
        return result;
    }
    
    /**
     * 用户注册
     */
    public Map<String, Object> register(UserRegisterRequest request) {
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 检查用户名是否已存在
            if (userRepository.findByUsername(request.getUsername()).isPresent()) {
                result.put("success", false);
                result.put("message", "用户名已存在");
                return result;
            }
            
            // 检查昵称是否已存在
            if (userRepository.findByNickname(request.getNickname()).isPresent()) {
                result.put("success", false);
                result.put("message", "昵称已存在");
                return result;
            }
            
            // 创建新用户
            User newUser = new User();
            newUser.setUsername(request.getUsername());
            newUser.setPasswordHash(passwordEncoder.encode(request.getPassword()));
            newUser.setNickname(request.getNickname());
            newUser.setLevel(1);
            newUser.setExp(0L);
            newUser.setGold(1000L);  // 初始金币
            newUser.setGems(0L);
            newUser.setPower(100);
            newUser.setMaxPower(100L);
            newUser.setStatus(User.UserStatus.OFFLINE);
            newUser.setCreateTime(LocalDateTime.now());
            newUser.setUpdateTime(LocalDateTime.now());
            
            User savedUser = userRepository.save(newUser);
            
            result.put("success", true);
            result.put("message", "注册成功");
            result.put("userId", savedUser.getUserId());
            result.put("user", savedUser);
            
            logger.info("User registered successfully: {} (ID: {})", savedUser.getUsername(), savedUser.getUserId());
            
        } catch (Exception e) {
            result.put("success", false);
            result.put("message", "注册失败：" + e.getMessage());
            logger.error("Registration error", e);
        }
        
        return result;
    }
    
    /**
     * 用户登出
     */
    public void logout(Long userId) {
        User user = userRepository.findById(userId).orElse(null);
        if (user != null) {
            user.setStatus(User.UserStatus.OFFLINE);
            user.setLastLogoutTime(LocalDateTime.now());
            user.setIsOnline(false);
            userRepository.save(user);
            
            onlineUsers.remove(userId);
            userSessions.remove(userId);
            
            logger.info("User logged out: {} (ID: {})", user.getUsername(), userId);
        }
    }
    
    /**
     * 获取用户信息
     */
    public User getUserInfo(Long userId) {
        return userRepository.findById(userId).orElse(null);
    }
    
    /**
     * 更新用户信息
     */
    public User updateUserInfo(User user) {
        user.setUpdateTime(LocalDateTime.now());
        return userRepository.save(user);
    }
    
    /**
     * 增加用户经验
     */
    public void addUserExp(Long userId, long expAmount) {
        User user = userRepository.findById(userId).orElse(null);
        if (user != null) {
            user.addExp(expAmount);
            
            // 检查升级
            long expPerLevel = 1000;  // 每级所需经验
            int newLevel = (int) (1 + user.getExp() / expPerLevel);
            if (newLevel > user.getLevel()) {
                user.setLevel(newLevel);
                logger.info("User {} leveled up to {}", userId, newLevel);
            }
            
            userRepository.save(user);
        }
    }
    
    /**
     * 增加用户金币
     */
    public void addUserGold(Long userId, long amount) {
        User user = userRepository.findById(userId).orElse(null);
        if (user != null) {
            user.addGold(amount);
            userRepository.save(user);
        }
    }
    
    /**
     * 增加用户钻石
     */
    public void addUserGems(Long userId, long amount) {
        User user = userRepository.findById(userId).orElse(null);
        if (user != null) {
            user.addGems(amount);
            userRepository.save(user);
        }
    }
    
    /**
     * 恢复用户体力
     */
    public void recoverUserPower(Long userId, int amount) {
        User user = userRepository.findById(userId).orElse(null);
        if (user != null) {
            user.recoverPower(amount);
            userRepository.save(user);
        }
    }
    
    /**
     * 消耗用户体力
     */
    public boolean consumeUserPower(Long userId, int amount) {
        User user = userRepository.findById(userId).orElse(null);
        if (user != null && user.consumePower(amount)) {
            userRepository.save(user);
            return true;
        }
        return false;
    }
    
    /**
     * 更新用户战斗记录
     */
    public void updateBattleRecord(Long userId, boolean isWin) {
        User user = userRepository.findById(userId).orElse(null);
        if (user != null) {
            if (isWin) {
                user.setWinCount(user.getWinCount() + 1);
                user.setRankScore(user.getRankScore() + 10);  // 胜利增加10分
            } else {
                user.setLoseCount(user.getLoseCount() + 1);
                user.setRankScore(Math.max(0, user.getRankScore() - 5));  // 失败扣5分，最低0
            }
            userRepository.save(user);
        }
    }
    
    /**
     * 获取排名前N的玩家
     */
    public List<User> getTopPlayers(int limit) {
        return userRepository.findTopPlayers(limit);
    }
    
    /**
     * 获取在线用户数
     */
    public long getOnlineUserCount() {
        return onlineUsers.size();
    }
    
    /**
     * 获取所有在线用户
     */
    public Collection<User> getOnlineUsers() {
        return onlineUsers.values();
    }
    
    /**
     * 检查用户是否在线
     */
    public boolean isUserOnline(Long userId) {
        return onlineUsers.containsKey(userId);
    }
    
    /**
     * 获取用户会话
     */
    public UserSession getUserSession(Long userId) {
        return userSessions.get(userId);
    }
    
    /**
     * 删除用户
     */
    public void deleteUser(Long userId) {
        userRepository.deleteById(userId);
        onlineUsers.remove(userId);
        userSessions.remove(userId);
        logger.info("User deleted: ID={}", userId);
    }
    
    /**
     * 用户会话类
     */
    @lombok.Data
    @lombok.NoArgsConstructor(access = lombok.AccessLevel.PUBLIC)
    public static class UserSession {
        private Long userId;
        private String username;
        private String sessionId;
        private LocalDateTime loginTime;
        private LocalDateTime lastActiveTime = LocalDateTime.now();
        
        public void updateActivity() {
            this.lastActiveTime = LocalDateTime.now();
        }
    }
}
